package net.pimpas.web.jsf.renderers.datepicker.html;

import java.io.IOException;
import java.util.Locale;

import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlCommandButton;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.RenderKit;
import javax.faces.render.Renderer;

import net.pimpas.framework.PimpasFramework;
import net.pimpas.web.jsf.components.datepicker.UIDatePicker;
import net.pimpas.web.jsf.components.span.UISpan;
import net.pimpas.web.jsf.renderers.RendererBase;
import net.pimpas.web.jsf.util.ComponentUtils;

import org.apache.myfaces.shared_impl.renderkit.html.HTML;

public class HtmlDatePickerRenderer extends RendererBase {
	
	@SuppressWarnings("unchecked")
	@Override
	public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
		if(!component.isRendered()) return;
		if(!ComponentUtils.isCorrectComponentType(component, UIDatePicker.class)) return;
		
		super.initResourceManager(context, component);
		
		UIDatePicker datePicker = (UIDatePicker) component;
		
		RenderKit renderKit = context.getRenderKit();
		
		UISpan span = (UISpan) context.getApplication().createComponent(UISpan.COMPONENT_TYPE);
		span.setNoId(Boolean.TRUE);
		span.setStyleClass(UIDatePicker.DATE_PICKER_STYLE);
		
		datePicker.getAttributes().put("span", span);
		
		Renderer spanRenderer = renderKit.getRenderer(UISpan.COMPONENT_FAMILY, UISpan.COMPONENT_RENDER_TYPE);
		spanRenderer.encodeBegin(context, span);
		
		Renderer renderer = renderKit.getRenderer(HtmlInputText.COMPONENT_FAMILY, "javax.faces.Text");
		renderer.encodeEnd(context, component);
		
		this.appendButton( context, datePicker );
		
		this.initImports(context, datePicker);
	}
	
	@SuppressWarnings("unchecked")
	private void appendButton(FacesContext context, UIDatePicker datePicker) {
		
		UIComponent cp = ComponentUtils.getComponentById(datePicker, context,
				UIDatePicker.DATE_PICKER_BUTTON_ID,
				ComponentUtils.SERVER_ID);
		
		if(cp != null) return;
		
		HtmlCommandButton button = (HtmlCommandButton) 
			context.getApplication().createComponent(HtmlCommandButton.COMPONENT_TYPE);
		button.setId(UIDatePicker.DATE_PICKER_BUTTON_ID);
		button.setValue("...");
		button.setStyleClass(UIDatePicker.DATE_PICKER_BUTTON_STYLE);
		button.setOnclick(datePicker.getId()+"_open()");
		button.setType("button");
		button.setDisabled(datePicker.isDisabled());
		datePicker.getChildren().add(button);
		datePicker.getAttributes().put(UIDatePicker.DATE_PICKER_BUTTON_ID, button.getClientId(context));
	}

	private void initImports(FacesContext context, UIDatePicker datePicker) {
		this.getResourceManager().addJavascriptHeader("js/"+UIDatePicker.DEFAULT_JS);
		this.getResourceManager().addJavascriptHeader("js/"+UIDatePicker.DEFAULT_SETUP_JS);
		// js language
		Locale l = PimpasFramework.getCurrentInstance().getContext().getLocale();
		String language = l.getLanguage();
		this.getResourceManager().addJavascriptHeader("js/language/"+language+"/calendar-"+language+".js");
		// import css
		// check theme
		if(UIDatePicker.checkTheme(datePicker.getTheme()))
			this.getResourceManager().addStylesheetHeader("css/"+datePicker.getTheme()+".css");
		else
			this.getResourceManager().addStylesheetHere(datePicker.getTheme());
	}

	@Override
	public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
		if(!component.isRendered()) return;
		if(!ComponentUtils.isCorrectComponentType(component, UIDatePicker.class)) return;
		
		UIDatePicker datePicker = (UIDatePicker) component;
		
		UISpan span = (UISpan) datePicker.getAttributes().remove("span");
		
		RenderKit renderKit = context.getRenderKit();
		
		Renderer spanRenderer = renderKit.getRenderer(UISpan.COMPONENT_FAMILY, UISpan.COMPONENT_RENDER_TYPE);
		spanRenderer.encodeEnd(context, span);
		
		// init javascript
		this.initJavascript(context, datePicker);
	}

	private void initJavascript(FacesContext context, UIDatePicker datePicker) throws IOException {
		ResponseWriter writer = context.getResponseWriter();
		String objectID = datePicker.getId();
		writer.startElement(HTML.SCRIPT_ELEM, datePicker);
		
		String onSelectedFunction = objectID+"_processSelected";
		String onClosedFunction   = objectID+"_processClosed";
		String openCalendar       = objectID+"_open";
		
		// open function
		
		writer.write("function "+openCalendar+"() {" +
				objectID+".showAtElement(document.getElementById('" +
				datePicker.getClientId(context)+
				"'));"+
		"};"
		);
		
		// onClose function
		
		writer.write("function "+onClosedFunction+"(obj) {" +
				"obj.hide();" +
		"};"
		);
		
		// onSelect function
		
		writer.write("function "+onSelectedFunction+"(obj, value) {" +
				"document.getElementById('"+
				datePicker.getClientId(context)+
				"').value = value;"+
		"};"
		);
		
		// create calendar
		String datevalue = (datePicker.getValue() != null) ? "'"+datePicker.getValue().toString()+"'" : null;
		writer.write("var "+objectID+" = new Calendar("+
				datePicker.getFirstDayOfWeek()+","+
				datevalue+", "+
				onSelectedFunction+", "+
				onClosedFunction+");"
		);
		
		writer.write(objectID+".weekNumbers = "+datePicker.getShowWeekNumbers()+";");
		writer.write(objectID+".setDateFormat('"+datePicker.getDateFormat()+"');");
		writer.write(objectID+".create( );");
		
		writer.endElement(HTML.SCRIPT_ELEM);
	}
	
	@Override
	public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
		RenderKit renderKit = context.getRenderKit();
		Renderer renderer = renderKit.getRenderer(HtmlInputText.COMPONENT_FAMILY, "javax.faces.Text");
		renderer.encodeChildren(context, component);
	}
	
	@Override
	public void decode(FacesContext context, UIComponent component) {
		RenderKit renderKit = context.getRenderKit();
		Renderer renderer = renderKit.getRenderer(HtmlInputText.COMPONENT_FAMILY, "javax.faces.Text");
		renderer.decode(context, component);
	}
}